package com.example.edianzu.somur.api.manager;

import com.example.edianzu.somur.App;
import com.example.edianzu.somur.api.ActivateMembershipCardService;
import com.example.edianzu.somur.api.BaseAPI;
import com.example.edianzu.somur.api.ExerciseService;
import com.example.edianzu.somur.api.HealthService;
import com.example.edianzu.somur.api.LoginService;
import com.example.edianzu.somur.api.MineService;
import com.example.edianzu.somur.api.bean.ActivateMembershipCard;
import com.example.edianzu.somur.api.bean.LoginInfo;
import com.example.edianzu.somur.api.bean.ResetPassword;
import com.example.edianzu.somur.api.bean.VerificationCode;
import com.example.edianzu.somur.module.exercise.bean.BannerInfo;
import com.example.edianzu.somur.module.exercise.bean.ExerciseInfo;
import com.example.edianzu.somur.module.health.bean.HealthPlan;
import com.example.edianzu.somur.module.mine.bean.BoundSample;
import com.example.edianzu.somur.module.mine.bean.RevisePassword;
import com.example.edianzu.somur.module.mine.bean.SampleList;
import com.example.edianzu.somur.utils.content.L;
import com.example.edianzu.somur.utils.content.NetworkState;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * author：风不会停息 on 2017/7/19 15:34
 * mailbox：yh131412hys@163.com
 * project：MyApplication
 * tel：13295355900
 * describe：
 */

public class APIManager {

    /*拦截器可以用来转换，重试，重写请求的机制。
 在注册拦截器时，可以注册成两类拦截器，分别为应用拦截器（Application Interceptors）和网络拦截器（Network Interceptors）
            1）应用拦截器
    不需要担心中间过程的响应,如重定向和重试.
            总是只调用一次,即使HTTP响应是从缓存中获取.
            观察应用程序的初衷. 不关心OkHttp注入的头信息如: If-None-Match.
    允许短路而不调用 Chain.proceed(),即中止调用.
    允许重试,使 Chain.proceed()调用多次.
            2）网络拦截器
    能够操作中间过程的响应,如重定向和重试.
            当网络短路而返回缓存响应时不被调用.
            只观察在网络上传输的数据.
            携带请求来访问连接.*/

    /*
比如对URL进行验证（如果Url中没有包含androidxx关键字，则修改请求链接为http://www.androidxx.cn），代码如下：

Interceptor appInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {

            Request request = chain.request();

            HttpUrl url = request.url();
            String s = url.url().toString();
            Response  response = null;
            //如果Url中没有包含androidxx关键字，则修改请求链接为http://www.androidxx.cn
            if (s.contains("androidxx")) {
                request = request.newBuilder().url(“http://www.androidxx.cn”).build();
            }
            response = chain.proceed(request);

            return response;
        }
    };
    */

    /**
     * 应用拦截器
     */
    Interceptor appInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            HttpUrl url = request.url();
            String s = url.url().toString();
            //———请求之前—–
            L.d("app interceptor:begin");
            Response  response = chain.proceed(request);
            L.d("app interceptor:end");
            //———请求之后————
            return response;
        }

    };
    /**
     * 网络拦截器
     */
    Interceptor networkInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            //———请求之前—–
            L.d("network interceptor:begin");
            Response  response = chain.proceed(request);
            L.d("network interceptor:end");
            return response;
        }
    };

    private static final int DEFAULT_TIMEOUT = 10;
//    实例化一个拦截器
    private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {

            //———请求之前————
            Request request = chain.request();

            //———请求之后————
            Response response = chain.proceed(chain.request());
            if (NetworkState.isNetworkConnected(App.getApp())) {

                int maxAge = 60 * 10; // 在线缓存在10分钟内可读取
                return response.newBuilder()
                        .removeHeader("Pragma")
                        .removeHeader("Cache-Control")
                        .header("Cache-Control", "public, max-age=" + maxAge)
                        .build();
            } else {

                int maxStale = 60 * 60 * 24 * 2; // 离线时缓存保存2天
                return response.newBuilder()
                        .removeHeader("Pragma")
                        .removeHeader("Cache-Control")
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .build();
            }
        }
    };

    private static final File httpCacheDirectory = new File(App.getApp().getCacheDir(), "[缓存目录]");
    private static final int cacheSize = 10 * 1024 * 1024; // 10 MiB 缓存大小
    private static final Cache cache = new Cache(httpCacheDirectory, cacheSize);//创建缓存

//    配置拦截器
    private static OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)//设置连接超时的时间
        .addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)//添加网络拦截器
        .addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
        .cache(cache)//添加缓存
        .build();

    private APIManager(){

    }

    private static final APIManager API_MANAGER=new APIManager();

    public static APIManager getApiManagerInstance(){

        return API_MANAGER;
    }

    /**
     * gson解析和生成带时间格式的数据
     * @author Administrator
    public class gsondate {
        static class User{
            Date brith;
            String name;
        }

        public static void main(String[] args) {

            Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
            User user=new User();
            user.name="lmw";
            user.brith=new Date();
            System.out.println(gson.toJson(user));

            //Gson gson=new Gson();
            String jsonStr="{'brith':'2013-11-20','name':'lmw'}";
            User uu=gson.fromJson(jsonStr, User.class);
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(uu.brith));
        }
    }*/

    /**
     * 处理时间
     */
    private Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
            .create();

    private Retrofit getRetrofit(String baseUrl){

        return new Retrofit.Builder()
                .client(client)
                .baseUrl(baseUrl)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//增加返回值为Observable<T>的支持
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }

    /*
    Schedulers.immediate(): 直接在当前线程运行，相当于不指定线程。这是默认的 Scheduler。
Schedulers.newThread(): 总是启用新线程，并在新线程执行操作。
Schedulers.io(): I/O 操作（读写文件、读写数据库、网络信息交互等）所使用的 Scheduler。行为模式和 newThread() 差不多，区别在于 io() 的内部实现是是用一个无数量上限的线程池，可以重用空闲的线程，因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中，可以避免创建不必要的线程。
Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算，即不会被 I/O 等操作限制性能的操作，例如图形的计算。这个 Scheduler 使用的固定的线程池，大小为 CPU 核数。不要把 I/O 操作放在 computation() 中，否则 I/O 操作的等待时间会浪费 CPU。
另外， Android 还有一个专用的 AndroidSchedulers.mainThread()，它指定的操作将在 Android 主线程运行。*/

    /*Observable.just(1, 2, 3, 4)
    .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程
    .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
    .subscribe(new Action1<Integer>() {
        @Override
        public void call(Integer number) {
            Log.d(tag, "number:" + number);
        }
    });
    由于 subscribeOn(Schedulers.io()) 的指定，被创建的事件的内容 1、2、3、4 将会在 IO 线程发出；
    而由于 observeOn(AndroidScheculers.mainThread()) 的指定，因此 subscriber 数字的打印将发生在主线程 。
    事实上，这种在 subscribe() 之前写上两句 subscribeOn(Scheduler.io()) 和 observeOn(AndroidSchedulers.mainThread()) 的使用方式非常常见，它适用于多数的 『后台线程取数据，主线程显示』的程序策略。

    RxJava 有四个基本概念：
	     Observable (可观察者，即被观察者)、 Observer (观察者)、 subscribe (订阅)、事件。
	     Observable 和 Observer 通过 subscribe() 方法实现订阅关系，从而 Observable 可以在需要的时候发出事件来通知 Observer。
    */

    /**
     * 获取登录信息
     * @param observer
     * @param username
     * @param password
     * @param company_id
     */
    public void getLoginInfo(Observer<LoginInfo> observer, String username, String password, String company_id){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(LoginService.class)
                .getLoginInfo(username,password,company_id)
                .subscribeOn(Schedulers.io())//指定subscribe发生的线程
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 获取健康回访列表
     * @param observer
     * @param member_id
     */
    public void getHealthList(Observer<HealthPlan> observer,String member_id){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(HealthService.class)
                .getHealthList(member_id)
                .subscribeOn(Schedulers.io())//指定subscribe发生的线程
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 返回已查看的方案
     * @param observer
     * @param id
     */
    public void isCheck(Observer<HealthPlan> observer,int id){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(HealthService.class)
                .isCheck(id)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 获取门店活动信息
     * @param observer
     * @param company_id
     */
    public void getExerciseInfo(Observer<ExerciseInfo> observer,String company_id,int type){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(ExerciseService.class)
                .getExerciseInfo(company_id,type)
                .subscribeOn(Schedulers.io())//指定subscribe发生的线程
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 获取轮播图信息
     * @param observer
     * @param company_id
     */
    public void getBannerInfo(Observer<BannerInfo> observer, String company_id,int type){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(ExerciseService.class)
                .getBannerInfo(company_id,type)
                .subscribeOn(Schedulers.io())//指定subscribe发生的线程
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 修改密码
     * @param observer
     * @param fields
     */
    public void setModifyPassword(Observer<RevisePassword> observer, Map<String,String> fields){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(MineService.class)
                .setModifyPassword(fields)
                .subscribeOn(Schedulers.io())//指定subscribe发生的线程
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 添加样本
     * @param observer
     * @param sample_sn
     * @param member_id
     */
    public void getBoundSample(Observer<BoundSample> observer,String sample_sn,String member_id){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(MineService.class)
                .getBoundSample(sample_sn,member_id)
                .subscribeOn(Schedulers.io())//指定subscribe发生的线程
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 获取样本列表
     * @param observer
     * @param member_id
     */
    public void getSampleList(Observer<SampleList> observer,String member_id){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(MineService.class)
                .getSampleList(member_id)
                .subscribeOn(Schedulers.io())//指定subscribe发生的线程
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 激活会员卡
     * @param observer
     * @param card_no
     * @param card_code
     * @param member_id
     */
    public void getActivateMembershipCard(Observer<ActivateMembershipCard> observer, String card_no,String card_code,String member_id){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(ActivateMembershipCardService.class)
                .getActivateInfo(card_no,card_code,member_id)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     * 获取短信验证码
     * @param observer
     * @param mobile
     * @param company_id
     */
    public void getSMSVerificationCode(Observer<VerificationCode> observer,String mobile,String company_id){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(LoginService.class)
                .getVerificationCode(mobile,company_id)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    /**
     *重置密码
     * @param observer
     * @param username
     * @param company_id
     * @param password
     */
    public void setResetPassword(Observer<ResetPassword> observer, String username,String company_id,String password){

        APIManager.getApiManagerInstance().getRetrofit(BaseAPI.HOST_URL)
                .create(LoginService.class)
                .setResetPassword(username, company_id, password)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }
}
